Skip to content

fix(publish): fail closed when a present witness signature was never verified (#4 HIGH-1)#124

Merged
ruvnet merged 1 commit into
mainfrom
fix/publish-fail-closed-unverified-witness
Jul 7, 2026
Merged

fix(publish): fail closed when a present witness signature was never verified (#4 HIGH-1)#124
ruvnet merged 1 commit into
mainfrom
fix/publish-fail-closed-unverified-witness

Conversation

@ruvnet

@ruvnet ruvnet commented Jul 7, 2026

Copy link
Copy Markdown
Owner

What / why

Fixes HIGH-1 from the AQE beta-feedback (#4). Witness verification is a guaranteed no-op: no kernel backend exposes witnessVerify, so witness-client.ts's crypto-verify delegate always falls through to the shape-only degraded path, which returned {valid:true}. publish.ts only threw on !valid, so a shape-valid witness.json carrying a garbage signature (64-hex key, 128-hex sig, schema 1) sailed through and the harness published as "signed" — a signature that was never checked.

Change (JS-only — closes the publish exploit without the native verifier)

  • witness-client.ts: VerificationResult gains unverified?: boolean; the degraded path sets it. valid stays true so read-only verify/doctor diagnostics are unchanged (they only assert shape).
  • publish.ts: a present-but-unverified witness now fails closed"Refusing to publish this harness as signed" — unless the caller passes allowUnverified, which then warns the signature was not checked.
  • publish-cmd.ts: --allow-unverified-witness flag + a loud warning line.

Live-verify (real harness publish)

Shape-valid witness, garbage 128-hex signature:

FAIL: witness present at …/witness.json but its signature was NOT cryptographically verified …
      Refusing to publish this harness as signed. Re-run with --allow-unverified-witness …

With --allow-unverified-witness: proceeds (dry-run) after the ⚠️ warning.

Tests

  • 2 new (publish.test.ts): the garbage-sig witness is refused; allowUnverified lets it proceed.
  • The degraded verify test still reports VALID (diagnostics unchanged).
  • Full create-agent-harness suite 363/363; tsc clean.

Not in this PR (native-publish-gated)

Wiring a real witnessVerify through NAPI+WASM so a genuine signature can actually be cryptographically checked (the rest of HIGH-1's fix). Until then, publishing a "signed" harness requires the explicit --allow-unverified-witness acknowledgement — no silent false "verified" claim.

🤖 Generated with claude-flow

…verified (#4 HIGH-1)

Beta feedback #4 (HIGH-1): witness verification is a guaranteed no-op — no kernel backend exposes
witnessVerify, so witness-client.ts's crypto-verify delegate always falls through to the shape-only
degraded path, which returned {valid:true}. publish.ts only threw on !valid, so a shape-valid
witness.json carrying a GARBAGE signature (64-hex key, 128-hex sig, schema 1) sailed through and the
harness published as "signed" — a signature that was never checked.

This closes the publish exploit without needing the (native-publish-gated) NAPI/WASM verifier:
- witness-client.ts: VerificationResult gains `unverified?: boolean`; the degraded path now sets it
  (valid stays true so read-only `verify`/`doctor` diagnostics are unchanged — they only assert shape).
- publish.ts: a present-but-unverified witness now FAILS CLOSED ("Refusing to publish this harness as
  signed") unless the caller passes allowUnverified — which then warns the signature was NOT checked.
- publish-cmd.ts: `--allow-unverified-witness` flag + a loud warning line.

Live-verified via real `harness publish`: a shape-valid, garbage-128-hex-sig witness now fails closed
(exit 1, clear message); `--allow-unverified-witness` proceeds with the warning. 2 new tests (exploit
closed + explicit opt-in); the degraded `verify` test still reports VALID; full create-agent-harness
suite 363/363; tsc clean.

Not in this PR (needs Rust + NAPI/WASM export, native-publish-gated): wiring a real witnessVerify so a
GENUINE signature can be cryptographically checked. Until then publishing a "signed" harness requires
the explicit --allow-unverified-witness acknowledgement.

Co-Authored-By: claude-flow <ruv@ruv.net>
@ruvnet ruvnet merged commit 096b173 into main Jul 7, 2026
25 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant